home *** CD-ROM | disk | FTP | other *** search
- unit WindowMenu;
-
- interface
-
- implementation
-
- uses
- Windows, Messages, CommonStuff, Menus, Forms, SysUtils, Dialogs;
-
- type
- TWindowMenu = class(TObject)
- private
- FWindowMenu,
- FWindowMenuOption: TMenuItem;
- protected
- procedure DoWindowMenu(Sender: TObject);
- procedure DoWindowMenuClick(Sender: TObject);
- procedure DoWindowItemClick(Sender: TObject);
- procedure SetWindowMenu(Value: Boolean);
- public
- constructor Create;
- destructor Destroy; override;
- end;
-
- resourcestring
- SWindow = 'W&indow'; //Default Window menu caption
- SInspector = 'Object Inspector'; //Object Inspector window caption
- SWindowMenu = '&Window menu'; //Window menu toggle option
-
- const
- SMainMenu = 'MainMenu1'; //Delphi's main form TMainMenu component
- SHelp = 'HelpMenu'; //Delphi's help menu component
- SFormat = '&%d %s'; //Format for Window menu item
- SIconCaptionClass = '#32772'; //Class name of an NT 3.5 icon caption
- //Registry strings
- SRegWindowMenu = 'Window Menu';
- SRegWindowMenuName = 'Window Menu Caption';
-
- constructor TWindowMenu.Create;
- begin
- inherited Create;
- //Make sure there is an options menu - bear in mind
- //that the other options code might not be being used
- Stuff.AddOptionsItem;
- //Set up Window menu options menu item
- FWindowMenuOption := NewItem(SWindowMenu, 0,
- Stuff.Ini.ReadBool(SRegSection, SRegWindowMenu, False),
- True, DoWindowMenu, 0, '');
- //Insert the menu item
- Stuff.FOptions.Add(FWindowMenuOption);
- //Set the window menu as appropriate
- SetWindowMenu(FWindowMenuOption.Checked);
- end;
-
- destructor TWindowMenu.Destroy;
- begin
- //Save Window menu existence state
- Stuff.Ini.WriteBool(SRegSection,
- SRegWindowMenu, FWindowMenuOption.Checked);
- //Delete Window menu
- SetWindowMenu(False);
- inherited Destroy
- end;
-
- procedure TWindowMenu.DoWindowMenu(Sender: TObject);
- begin
- //When user toggles Window menu option, set
- //checkmark and set Window menu accordingly
- with Sender as TMenuItem do
- begin
- Checked := not Checked;
- SetWindowMenu(Checked)
- end
- end;
-
- procedure TWindowMenu.DoWindowMenuClick(Sender: TObject);
- var
- Loop, Count, OldCount, PID: Integer;
- Item: TMenuItem;
- Wnd: HWnd;
- WndClass, WndCaption: array[0..255] of Char;
- begin
- //Delphi repetitively calls the OnClick events of the
- //main menu items to allow IDE code to en/disable
- //speedbuttons as necessary. We will only execute
- //this code if it is a real menu click (Sender =
- //the menu item) - not a fake one from Delphi (where
- //Sender = the main window)
- if Sender = FWindowMenu then
- begin
- Count := 0;
- //It would normally be sensible to delete the old items
- //and then add new items. But for some reason that goes
- //screwy UI-wise, so instead we add the new ones and
- //then delete the old ones
- //So, how many Window menu items were there?
- OldCount := FWindowMenu.Count;
- //Add new menu items for current windows
- Wnd := GetWindow(Application.Handle, gw_HWndFirst);
- while Wnd <> 0 do
- begin
- GetClassName(Wnd, WndClass, 255);
- GetWindowThreadProcessID(Wnd, @PID);
- //We only want windows in the Window menu
- //that are... visible, enabled, have a caption,
- //are not icon captions, are part of the Delphi
- //process and are not the Application window
- if IsWindowVisible(Wnd) and
- IsWindowEnabled(Wnd) and
- (GetWindowText(Wnd, WndCaption, 255) > 0) and
- (PID = GetCurrentProcessID) and
- (StrPas(WndClass) <> SIconCaptionClass) and
- (StrPas(WndClass) <> Application.ClassName) then
- begin
- Inc(Count);
- //Make a new menu item, remembering to put the
- //checkmark on the currently selected page
- Item := NewItem(Format(SFormat, [Count, StrPas(WndCaption)]), 0,
- Wnd = Screen.ActiveCustomForm.Handle,
- True, DoWindowItemClick, 0, '');
- Item.RadioItem := True;
- //Set up some unique group index to make
- //menu items work like radio buttons
- Item.GroupIndex := 57;
- //Put F11 next to Object Inspector item as a reminder
- if StrPas(WndCaption) = SInspector then
- Item.ShortCut := vk_F11; //Don't use TextToShortCut!!
- FWindowMenu.Add(Item);
- //Ensure the menu item has a reference to the relevant form
- Item.Tag := Wnd;
- end;
- Wnd := GetWindow(Wnd, gw_HWndNext)
- end;
- //Add About menu item
- FWindowMenu.Add(NewLine);
- FWindowMenu.Add(NewItem(SAbout, 0, False, True, Stuff.DoAbout, 0, ''));
- //Now delete the old (potentially wrong) window menu items
- for Loop := 1 to OldCount do
- FWindowMenu.Items[0].Free;
- end
- end;
-
- procedure TWindowMenu.DoWindowItemClick(Sender: TObject);
- begin
- //Restore selected window (in case it was minimised)
- PostMessage((Sender as TMenuItem).Tag, wm_SysCommand, sc_Restore, 0);
- //Make selected window active
- SetForegroundWindow((Sender as TMenuItem).Tag)
- end;
-
- procedure TWindowMenu.SetWindowMenu(Value: Boolean);
- var
- FHelpMenuItem,
- FMainMenuItem: TMenuItem;
- begin
- if Value then
- begin
- //This finds the Help menu, which the Window menu will sit before
- FHelpMenuItem := GetComponent(Application.MainForm, SHelp, SGenericError + SHelp) as TMenuItem;
- //This adds a Window menu onto the end of Delphi's main menu
- //with a caption read from the registry (some people are fussy
- //about main menu captions)
- FWindowMenu := NewItem(
- Stuff.Ini.ReadString(SRegSection, SRegWindowMenuName, SWindow),
- 0, False, True, DoWindowMenuClick, 0, '');
- //Add a dummy menu item to allow later manipulation logic to work
- //If we don't, the menu ends up elsewhere on the screen
- FWindowMenu.Add(NewLine);
- //Get starting point for new main menu items
- FMainMenuItem := Application.MainForm.Menu.Items;
- FMainMenuItem.Add(FWindowMenu);
- //Make new Window menu sit before the Help menu
- FHelpMenuItem.MenuIndex := FMainMenuItem.Count;
- end
- else
- begin
- //This deletes the Window menu
- FWindowMenu.Free;
- FWindowMenu := nil
- end
- end;
-
- var
- WindowMenuObject: TWindowMenu;
-
- initialization
- try
- WindowMenuObject := TWindowMenu.Create
- except
- on E: Exception do
- ShowMessage(SSetupError + ': ' + E.Message)
- end
- finalization
- WindowMenuObject.Free
- end.
-